#!/usr/bin/python
#
# this is alpha stage SW !
#
# DEPENDENCIES
# - numpy (install via package manager)
# - PILLOW (install via package manager)
#
#How to use it:
#python sq-cleaner.py -q5 img_6524.jpg
# all arguments not starting with "-" are considered images
#(intended for python2.7 and 3.x)
#
#any number of image files (wildcards allowed)
#(I presume you are working on linux)
# use "-h" for more info


from __future__ import division
from random import random
from sys import argv
import math
import CS_convertor
import numpy as np
from os.path import split,splitext
from time import time

sqinnersize=2
newsize=0
halfmode=False


version="0.0.1"

def cleaning_sq(innersize,workingarray):
	changed=0
	for x in range(0,imgX-innersize-2):
		for y in range(0,imgY-innersize-2):	
			minvalue=300
			maxvalue=-100
			#scanning outer pixels of square
			for i in range(innersize+1):
				#A
				startx=x
				starty=y
				#step=x+i
				localvalue=workingarray[startx+i,starty]
				if localvalue<minvalue:
					minvalue=localvalue
				if localvalue>maxvalue:
					maxvalue=localvalue
				#B
				startx=x
				starty=y
				#step=y+i
				localvalue=workingarray[startx,starty+i]
				if localvalue<minvalue:
					minvalue=localvalue
				if localvalue>maxvalue:
					maxvalue=localvalue
				#C				
				startx=x+innersize+1
				starty=y
				#step=y+i					
				localvalue=workingarray[startx,starty+i]
				if localvalue<minvalue:
					minvalue=localvalue
				if localvalue>maxvalue:
					maxvalue=localvalue			
				#D
				startx=x
				starty=y+innersize+1
				#step=x+i					
				localvalue=workingarray[startx+i,starty]
				if localvalue<minvalue:
					minvalue=localvalue
				if localvalue>maxvalue:
					maxvalue=localvalue		


			#print (minvalue,maxvalue)

			#changing inner pixels
			for x_l in range (1,1+innersize):
				for y_l in range (1,1+innersize):
					if workingarray[x+x_l,y+y_l]<minvalue:
						#print (minvalue,maxvalue)
						#print (workingarray[x+x_l,y+y_l])
						workingarray[x+x_l,y+y_l]=minvalue
						changed=changed+1
						#print (changed)
					if workingarray[x+x_l,y+y_l]>maxvalue:
						workingarray[x+x_l,y+y_l]=maxvalue
						changed=changed+1		
	return changed			


try:
	from PIL import Image      # necessary for manipulation with images
except:
	print (" Warning: Failed to load Pillow (Imaging) modules!")
	print (" Pillow (fork of PIL) should be available in repositories")
	print (" of your distribution, please install it first.")
	exit()

print ("[sq-cleaner.py, version: "+str(version)+", use '-h' for help and bit more info]")

files=[]
#parsing arguments
for arg in argv[1:]:
	if arg=="-H":	
		halfmode=True
		print (" Halfmode...")
	if arg.startswith("-Q"):
		try:
			sqinnersize=int(arg[2:])
		except:
			print ("Failed to get inner size for sq cleaning:" + str(arg[2:])+" ???")
			#sqinnersize=0
		
		if (sqinnersize<1):
			sqinnersize=1
		if (sqinnersize>20):
			sqinnersize=20
		print (" New inner size for square cleaning: "+str(sqinnersize))
	if arg=="-S":	
		withstats=True
		print (" Statistics will be printed on image...")
	if arg.startswith("-s"):
		#print (arg[2:])
		try:
			newsize=int(arg[2:])
		except:
			print ("Failed to get new size:" + str(arg[2:])+" ???")
			newsize=0
		
		if (newsize<10):
			newsize=10
		if (newsize>2500):
			newsize=2500
		print (" New size: "+str(newsize))
	if arg.startswith("-h") or arg.startswith("--help"):
		print (" ")
		print ("sq-cleaner.py "+version)
		print ("Available switches")
		print ("-s#  where # is width of image (no space)")	
		print ("-b  blur the image before processing(no intensity/number is to be given)")	
		print ("-Q#  set the inner size for square-cleaning")	
		print ("-H  halfmode")	
		print (" ")
		print ("This is prototype/alpha level software... ")	
		print ("Contact: tiborb95 at gmail dot com ")		
		exit (0)
		
	if not arg.startswith("-"):
		files.append(arg)

imgcount=0	
for image in files:

	imgcount=imgcount+1	
	
	# trying to open image
	try:
		sourceImg = Image.open(image)
		sourceImg_loaded=sourceImg.load()

	except:
		print ("Cannot open "+image+" image, skipping this one...")
		continue
	
	print ("\nProcessing: "+image+"  "+str(imgcount)+"/"+str(len(files)))	
	#corename=image.rstrip(".PpjJpNnPgG")
	corename=splitext(split(image)[1])[0]	
	#finalImg=sourceImg
	
	#resizing if needed
	imgX,imgY=sourceImg.size
	if newsize>0 and imgX > newsize:
		print (" Resizing...")

		sourceImg=sourceImg.resize((newsize,int(newsize/imgX*imgY)),Image.ANTIALIAS)
		sourceImg_loaded=sourceImg.load()
	
	
	# BODY
	imgX,imgY=sourceImg.size
	newImage = Image.new( 'RGB', (imgX,imgY), "black") 
	Routput=np.zeros((imgX,imgY))
	Goutput=np.zeros((imgX,imgY))
	Boutput=np.zeros((imgX,imgY))
	
	for x in range(0,imgX):
		for y in range(0,imgY):
			R=sourceImg_loaded[x,y][0]
			G=sourceImg_loaded[x,y][1]
			B=sourceImg_loaded[x,y][2]
			Routput[x,y]=R
			Goutput[x,y]=G
			Boutput[x,y]=B

			
	print (" squarecleaning changed pixels:     R       G     B    Overall           sec")
	cleaned=1000000
	while cleaned>imgX*imgY*0.005:
		t1 = time()
		lchanged=cleaning_sq(sqinnersize,Routput) #other values, same values in other, difftreshols
		achanged=cleaning_sq(sqinnersize,Goutput) 
		bchanged=cleaning_sq(sqinnersize,Boutput) 
		t2 = time()
		cleaned=lchanged+achanged+bchanged
		print (" squarecleaning changed pixels: "+str(lchanged).rjust(6)+" "+str(achanged).rjust(6)+" "+str(bchanged).rjust(6)+" = "+str(cleaned/imgX/imgY*100.0)[:5].rjust(6)+"% , time: "+str(t2-t1)[:5].rjust(6))

	
	#inserting final values to image
	for x in range(0,imgX):
		for y in range(0,imgY):	
			#print (Routput[x,y],Goutput[x,y],Goutput[x,y])
			if halfmode==True and x<imgX/2.5:
				R=sourceImg_loaded[x,y][0]
				G=sourceImg_loaded[x,y][1]
				B=sourceImg_loaded[x,y][2]
				newImage.putpixel((x,y),(R,G,B))
			elif halfmode==True and x<imgX/2.5+5:
				R=sourceImg_loaded[x,y][0]
				G=sourceImg_loaded[x,y][1]
				B=sourceImg_loaded[x,y][2]
				newImage.putpixel((x,y),(255-R,255-G,255-B))
			else:
				newImage.putpixel((x,y),( int(Routput[x,y]) , int(Goutput[x,y]) , int(Boutput[x,y])) )
	
	
	
	newname="sqClean_"+corename+".jpg"
	print( " Saving as: "+newname)
	newImage.save(newname,quality=95)
	newname="sqClean_"+corename+".png"
	print( " Saving as: "+newname)
	newImage.save(newname,optimize=True)	 		
